Android类似微信聊天的页面开发教程(Kotlin)三 |
您所在的位置:网站首页 › android studio微信聊天界面代码 › Android类似微信聊天的页面开发教程(Kotlin)三 |
前提条件 安装并配置好Android Studio Android Studio Electric Eel | 2022.1.1 Patch 2 Build #AI-221.6008.13.2211.9619390, built on February 17, 2023 Runtime version: 11.0.15+0-b2043.56-9505619 amd64 VM: OpenJDK 64-Bit Server VM by JetBrains s.r.o. Windows 11 10.0 GC: G1 Young Generation, G1 Old Generation Memory: 1280M Cores: 6 Registry: external.system.auto.import.disabled=true ide.text.editor.with.preview.show.floating.toolbar=false ide.balloon.shadow.size=0 Non-Bundled Plugins: com.intuit.intellij.makefile (1.0.15) com.github.setial (4.0.2) com.alayouni.ansiHighlight (1.2.4) GsonOrXmlFormat (2.0) GLSL (1.19) com.mistamek.drawablepreview.drawable-preview (1.1.5) com.layernet.plugin.adbwifi (1.0.5) com.likfe.ideaplugin.eventbus3 (2020.0.2) gradle-wrapper.properties #Tue Apr 25 13:34:44 CST 2023 distributionBase=GRADLE_USER_HOME distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-bin.zip distributionPath=wrapper/dists zipStorePath=wrapper/dists zipStoreBase=GRADLE_USER_HOMEbuild.gradle(:Project) // Top-level build file where you can add configuration options common to all sub-projects/modules. plugins { id 'com.android.application' version '7.3.1' apply false id 'com.android.library' version '7.3.1' apply false id 'org.jetbrains.kotlin.android' version '1.7.20' apply false }setting.gradle pluginManagement { repositories { google() mavenCentral() gradlePluginPortal() maven { url 'https://jitpack.io' } } } dependencyResolutionManagement { repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) repositories { google() mavenCentral() gradlePluginPortal() maven { url 'https://jitpack.io' } } } rootProject.name = "logindemo" include ':app'build.gralde(:app) plugins { id 'com.android.application' id 'org.jetbrains.kotlin.android' } android { namespace 'com.example.fechat' compileSdk 33 defaultConfig { applicationId "com.example.fechat" minSdk 26 targetSdk 33 versionCode 1 versionName "1.0" } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' } } compileOptions { sourceCompatibility JavaVersion.VERSION_11 targetCompatibility JavaVersion.VERSION_11 } kotlinOptions { jvmTarget = '1.8' } } dependencies { implementation 'androidx.core:core-ktx:1.7.0' implementation 'androidx.appcompat:appcompat:1.6.1' implementation 'com.google.android.material:material:1.8.0' implementation 'androidx.constraintlayout:constraintlayout:2.1.4' // 沉浸式状态栏 https://github.com/gyf-dev/ImmersionBar implementation 'com.gyf.immersionbar:immersionbar:3.0.0' implementation 'com.gyf.immersionbar:immersionbar-components:3.0.0' // fragment快速实现(可选) implementation 'com.gyf.immersionbar:immersionbar-ktx:3.0.0' // kotlin扩展(可选) implementation 'com.google.code.gson:gson:2.8.9' }对Kotlin语言有基本了解 内容在前一篇博客中写了基础配置,如果本篇内容看不懂,可以先去上一篇。 增加聊天页面 activity_message.xml中 标题+内容RecyclerView+底部输入框+发送 package com.example.fechat.activity import android.annotation.SuppressLint import android.os.Bundle import android.widget.EditText import android.widget.TextView import androidx.appcompat.app.AppCompatActivity import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView import com.example.fechat.R import com.example.fechat.adapter.ChatAdapter import com.example.fechat.bean.ChatBean import com.example.fechat.bean.MessageBean import com.google.gson.Gson import com.gyf.immersionbar.ImmersionBar class MessageActivity : AppCompatActivity() { private val beans: MutableList = ArrayList() private var adapter: ChatAdapter? = null private lateinit var itemView: RecyclerView private lateinit var chatBean: ChatBean override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) ImmersionBar.with(this) .statusBarDarkFont(true) .statusBarColor(R.color.title) .navigationBarColor(R.color.white) .navigationBarDarkIcon(true) .init() setContentView(R.layout.activity_message) val backTv = findViewById(R.id.backTv) val inputText: EditText = findViewById(R.id.inputText) val sendText: TextView = findViewById(R.id.sendText) val userName: TextView = findViewById(R.id.userName) backTv.setOnClickListener { finish() } sendText.setOnClickListener { sendText(inputText.text.toString()) } initItemRecyclerView() getBundle() userName.text = chatBean.nick } private fun getBundle() { val userInfo = intent.getStringExtra("UserInfo") chatBean = Gson().fromJson(userInfo, ChatBean::class.java) } private fun initItemRecyclerView() { itemView = findViewById(R.id.itemView) val layoutManager = LinearLayoutManager(this) layoutManager.orientation = RecyclerView.VERTICAL itemView.layoutManager = layoutManager adapter = ChatAdapter(beans) itemView.adapter = adapter } @SuppressLint("NotifyDataSetChanged") private fun sendText(message: String) { beans.add( MessageBean( message, "用户", false, System.currentTimeMillis() ) ) beans.add( MessageBean( message, chatBean.nick, true, System.currentTimeMillis(), true ) ) adapter?.notifyDataSetChanged() } } 制作聊天适配器适配器的xml中,分为两部分 主用户发送消息,同时接收聊天对象的消息 package com.example.fechat.adapter import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.widget.ImageView import android.widget.RelativeLayout import android.widget.TextView import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView.Adapter import com.example.fechat.R import com.example.fechat.bean.MessageBean import com.example.fechat.view.CircleImageView import java.text.SimpleDateFormat import java.util.* class ChatAdapter(private val data: List) : Adapter() { private fun getTime(time: Long): String { val sDateFormat = SimpleDateFormat("MM-dd HH:mm", Locale.getDefault()) return sDateFormat.format(time) } class BaseHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { val userLayout: RelativeLayout = itemView.findViewById(R.id.userLayout) val userHead: CircleImageView = itemView.findViewById(R.id.userHead) val userMessage: TextView = itemView.findViewById(R.id.userMessage) val userTime: TextView = itemView.findViewById(R.id.userTime) val respLayout: RelativeLayout = itemView.findViewById(R.id.respLayout) val respHead: CircleImageView = itemView.findViewById(R.id.respHead) val respMessage: TextView = itemView.findViewById(R.id.respMessage) val respTime: TextView = itemView.findViewById(R.id.respTime) val respImage: ImageView = itemView.findViewById(R.id.respImage) } override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BaseHolder { val view = LayoutInflater.from(parent.context).inflate(R.layout.item_message, null, false); return BaseHolder(view) } override fun getItemCount(): Int { return data.size } override fun onBindViewHolder(holder: BaseHolder, position: Int) { val item = data[position] if (item.isResponse) { holder.respLayout.visibility = View.VISIBLE holder.userLayout.visibility = View.GONE holder.respMessage.text = item.message holder.respTime.text = getTime(item.time) } else { holder.userLayout.visibility = View.VISIBLE holder.respLayout.visibility = View.GONE holder.userMessage.text = item.message holder.userTime.text = getTime(item.time) } } }聊天内容适配器中的data数据结构如下: package com.example.fechat.bean data class MessageBean( var message: String, var userName: String, var isResponse: Boolean = false, var time: Long, var isSuccess: Boolean = true )其中首页用户聊天列表中的data修改,主要是data转化为string方便intent传输,如下: package com.example.fechat.bean data class ChatBean( val head: String, val nick: String, val newest: String, val date: String ) { override fun toString(): String { return "{head:$head,nick:$nick,newest:$newest,date:$date}" } }首页用户聊天记录的适配器作如下修改,主要是增加了适配器点击事件监听器: package com.example.fechat.base import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.widget.TextView import androidx.recyclerview.widget.RecyclerView import com.example.fechat.R import com.example.fechat.bean.ChatBean class BaseAdapter(private val data: List) : RecyclerView.Adapter() { private lateinit var onItemClickListener: OnItemClickListener override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BaseHolder { val view = LayoutInflater.from(parent.context).inflate(R.layout.base_item, null, false); return BaseHolder(view) } override fun getItemCount(): Int { return data.size } override fun onBindViewHolder(holder: BaseHolder, position: Int) { holder.headTv.visibility = if (data[position].head.isEmpty()) View.GONE else View.VISIBLE holder.nickTv.visibility = if (data[position].nick.isEmpty()) View.GONE else View.VISIBLE holder.newestTv.visibility = if (data[position].newest.isEmpty()) View.GONE else View.VISIBLE holder.dateTv.visibility = if (data[position].date.isEmpty()) View.GONE else View.VISIBLE holder.headTv.text = data[position].head holder.nickTv.text = data[position].nick holder.newestTv.text = data[position].newest holder.dateTv.text = data[position].date holder.itemView.setOnClickListener { onItemClickListener.onItemClick(holder.itemView, position) } } class BaseHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { val headTv: TextView = itemView.findViewById(R.id.headTv) val nickTv: TextView = itemView.findViewById(R.id.nickTv) val newestTv: TextView = itemView.findViewById(R.id.newestTv) val dateTv: TextView = itemView.findViewById(R.id.dateTv) } fun setOnItemClickListener(onItemClickListener: OnItemClickListener) { this.onItemClickListener = onItemClickListener } interface OnItemClickListener { fun onItemClick(view: View, position: Int) } } 点击跳转到聊天页面 package com.example.fechat.fragment import android.content.Intent import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import androidx.fragment.app.Fragment import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView import com.example.fechat.R import com.example.fechat.activity.MessageActivity import com.example.fechat.base.BaseAdapter import com.example.fechat.bean.ChatBean class ChatFragment : Fragment() { private lateinit var recyclerView: RecyclerView override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View? { val view = inflater.inflate(R.layout.fragment_chat, container, false) recyclerView = view.findViewById(R.id.recyclerView) val data = ArrayList() data.add(ChatBean("头像0", "用户0", "聊天记录0", "4月25日")) data.add(ChatBean("头像1", "用户1", "聊天记录1", "4月24日")) data.add(ChatBean("头像2", "用户2", "聊天记录2", "4月23日")) data.add(ChatBean("头像3", "用户3", "聊天记录3", "4月22日")) data.add(ChatBean("头像4", "用户4", "聊天记录4", "4月21日")) data.add(ChatBean("头像5", "用户5", "聊天记录5", "4月20日")) data.add(ChatBean("头像6", "用户6", "聊天记录6", "4月19日")) data.add(ChatBean("头像7", "用户7", "聊天记录7", "4月18日")) data.add(ChatBean("头像8", "用户8", "聊天记录8", "4月17日")) data.add(ChatBean("头像9", "用户9", "聊天记录9", "4月16日")) recyclerView.layoutManager = LinearLayoutManager(context) val baseAdapter = BaseAdapter(data) recyclerView.adapter = baseAdapter baseAdapter.setOnItemClickListener(object : BaseAdapter.OnItemClickListener { override fun onItemClick(view: View, position: Int) { val intent = Intent(context, MessageActivity::class.java) intent.putExtra("UserInfo", data[position].toString()) startActivity(intent) } }) return view } } 开源地址FeChat: 模仿微信 |
今日新闻 |
推荐新闻 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |